package m.jclecai.com.base.digitalLottery;

import android.content.Intent;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.PopupWindow;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import butterknife.BindView;
import butterknife.OnClick;
import m.jclecai.com.R;
import m.jclecai.com.activity.WebHelperActivity;
import m.jclecai.com.adapter.lotteryNumberMenu.LotteryNumberAdapter;
import m.jclecai.com.bean.BallItem;
import m.jclecai.com.bean.LotteryNumberMenuBean;
import m.jclecai.com.bean.MissDataBean;
import m.jclecai.com.constant.Constant_Result;
import m.jclecai.com.listener.Callback;
import m.jclecai.com.listener.OnBallCheckedListener;
import m.jclecai.com.pop.GuideMenuPopupWindow;
import m.jclecai.com.pop.LotteryNumberPopWindow;
import m.jclecai.com.ui.LotteryHistoryActivity;
import m.jclecai.com.utils.CombineUtil;
import m.jclecai.com.utils.MakeRandomUtil;
import m.jclecai.com.utils.PreferenceUtil;
import m.jclecai.com.utils.ShakeUtils;
import m.jclecai.com.utils.http.FastOk;
import m.jclecai.com.view.NumberLotteryEffectView;

/**
 * Created by zed on 2018/3/21.
 */

public abstract class BaseNumberLotteryActivity extends DefaultDigitalLotteryActivity {
    //菜单数据
    protected List<LotteryNumberMenuBean> menuBeans;
    @BindView(R.id.rv_num_lottery)
    protected RecyclerView rvNumLottery;
    //有多行选择的数字彩适配器
    protected LotteryNumberAdapter adapter;
    protected LotteryNumberPopWindow mCenterPopWindow;
    protected GuideMenuPopupWindow mRightMenuPopupWindow;
    protected LotteryNumberMenuBean currentMenu;
    protected List<LotteryNumberMenuBean> mBetList = new ArrayList<>();
    private ShakeUtils mShakeUtils;

    @Override
    protected void initData() {
        super.initData();
        menuBeans = initMenuData();
        initCenterPopupWindow();
        initRightPopupWindow();
        requestIssueInfo();
        requestMissData(new Callback<MissDataBean>() {
            @Override
            public void callback(MissDataBean missDataBean) {
                super.callback(missDataBean);
                if (adapter != null) adapter.setMissDataBean(missDataBean);
            }
        });
        adapter = new LotteryNumberAdapter(menuBeans, this);
        rvNumLottery.setLayoutManager(new LinearLayoutManager(this));
        rvNumLottery.setAdapter(adapter);
        mShakeUtils = new ShakeUtils(this);

        mShakeUtils.setOnShakeUtilsListener(new ShakeUtils.OnShakeUtilsListener() {
            @Override
            public void onShakedListener() {
                if (currentMenu == null) currentMenu = menuBeans.get(0);
                currentMenu.setSelectBall(null);
                if (adapter != null) adapter.notifyDataSetChanged();
                LinkedList<String> balls = MakeRandomUtil.getBall(currentMenu.getItemLineCount(), currentMenu.getSelectBallCount());
                setRandomChecked(balls, false);
                shakedEffect(balls);
            }

            @Override
            public void hasNotVibratorListener() {

            }
        });
    }

    /**
     * 震动后的动画效果
     */
    private void shakedEffect(List<String> balls) {
        NumberLotteryEffectView.Builder
                .create(this)
                .fromZero(false)
                .setTargetEffectView(balls, rvNumLottery, currentMenu.getItemCount())
                .setCurrMode(NumberLotteryEffectView.BALL.RED)
                .setOnAnimatorListnener(new NumberLotteryEffectView.OnAnimatorListnener() {

                    @Override
                    public void onAnimatorEnd(List<View> mTargetEffectView) {
                        if (currentMenu != null) {
                            Map<Integer, Map<Integer, BallItem>> selectBall = currentMenu.getSelectBall();
                            for (Map<Integer, BallItem> map : selectBall.values()) {
                                for (BallItem ball : map.values()) {
                                    ball.setSelected(true);
                                }
                            }
                        }
                        if (adapter != null) adapter.notifyDataSetChanged();
                    }
                })
                .build()
                .attachToWindow()
                .startEffect();
    }

    public abstract List<LotteryNumberMenuBean> initMenuData();

    @Override
    protected void initListener() {
        super.initListener();
        if (adapter != null)
            adapter.setOnBallCheckedListener(new OnBallCheckedListener() {

                @Override
                public void onBallChecked(BallItem item) {
                    onBallCheck(item);
                }
            });
    }

    private void onBallCheck(BallItem item) {
        onBallCheck(item, null);
        getNFactorial();
    }

    //是否允许选中的小球有重复 true 允许小球重复
    protected boolean allowBallDuplicate() {
        return true;
    }

    /**
     * 如果有默认bean则优先使用
     *
     * @param item
     * @param bean
     */
    private void onBallCheck(BallItem item, LotteryNumberMenuBean bean) {
        boolean b = allowBallDuplicate();
        currentMenu = bean == null ? menuBeans.get(item.getDefCheckMenu()) : bean;
        if (currentMenu == null) return;

        Map<Integer, Map<Integer, BallItem>> selectBall = currentMenu.getSelectBall();
        if (!b) {
            if (selectBall != null) {
                //首先直接移除本行的所有球
                selectBall.remove(item.getLineIndex());
                adapter.notifyItemChanged(item.getLineIndex());
                //其余的行不允许小球重复 清除掉重复的小球
                Iterator<Map.Entry<Integer, Map<Integer, BallItem>>> iterator = selectBall.entrySet().iterator();
                while (iterator.hasNext()) {
                    Map<Integer, BallItem> map = iterator.next().getValue();
                    int lineIndex = -1;
                    if (map != null) {
                        for (BallItem ball : map.values()) {
                            //如果存在小球则移除
                            if (item.getPosition() == ball.getPosition()) {
                                lineIndex = ball.getLineIndex();
                                map.remove(ball.getPosition());
                                Log.e("移除", "移除第" + lineIndex + "行->球号码" + ball.getBallNum());
                            }
                        }
                    }
                    if (lineIndex > -1)
                        adapter.notifyItemChanged(lineIndex);
                    if (map.size() <= 0)
                        selectBall.remove(map);
                }
                if (selectBall.size() <= 0)
                    currentMenu.setSelectBall(null);
            }
        }
        //如果不存在球则直接添加
        if (selectBall == null) {
            selectBall = new LinkedHashMap<>();
            Map<Integer, BallItem> map = new LinkedHashMap<>();
            map.put(item.getPosition(), item);
            selectBall.put(item.getLineIndex(), map);
            currentMenu.setSelectBall(selectBall);
        } else {
            //如果有选过球了 则按照当前选择球的规则添加到对应的位置
            Map<Integer, BallItem> map = selectBall.get(item.getLineIndex());
            if (map == null) {
                map = new LinkedHashMap<>();
                map.put(item.getPosition(), item);
                selectBall.put(item.getLineIndex(), map);
            } else {
                BallItem ballItem = map.get(item.getPosition());
                if (ballItem == null)//点击之后会有个check=true的记录
                    map.put(item.getPosition(), item);
                else//如果已经存在则为check=false的记录 可以直接移除 避免最后拼接号码过多计算
                    map.remove(item.getPosition());
            }
            //这里同理 如果没有记录了则直接移除
            if (map.size() == 0)
                selectBall.remove(item.getLineIndex());
        }
        //这里同理 如果没有记录了则直接移除
        if (selectBall.size() == 0)
            currentMenu.setSelectBall(null);
//        if (!b)
//            adapter.notifyDataSetChanged();
    }

    //投注数目
    void getNFactorial() {
        if (currentMenu.getSelectBall() == null) {
            mTvNumberMoney.setVisibility(View.INVISIBLE);
            return;
        }
        if (currentMenu.getSelectBall().get(0) == null) {
            mTvNumberMoney.setVisibility(View.INVISIBLE);
            return;
        }

        int n = currentMenu.getSelectBallCount();
        int m = 0;
        Collection<Map<Integer, BallItem>> values = currentMenu.getSelectBall().values();
        for (Map<Integer, BallItem> map : values) {
            m += map.size();
        }
        if (m < n) return;
        long nFactorial = setUpCustomAlgorithm() > -1 ? setUpCustomAlgorithm() : CombineUtil.getNFactorial1(m, n);
        mTvNumberMoney.setText(nFactorial + "注" + "," + (nFactorial * 2) + "元");
        mTvNumberMoney.setVisibility(nFactorial > 0 ? View.VISIBLE : View.INVISIBLE);
        currentMenu.setNumber(nFactorial);
    }

    //设置自定义注数算法便于不同彩种算法不一致 返回注数
    public int setUpCustomAlgorithm() {
        return -1;
    }

    @Override
    protected boolean addBettingArea() {
        boolean isMatchItemCount = false;
        if (currentMenu != null && currentMenu.getSelectBall() != null) {
            Map<Integer, Map<Integer, BallItem>> selectBall = currentMenu.getSelectBall();
            int itemCount = currentMenu.getItemCount();
            int allBall = 0;
            for (int i = 0; i < itemCount; i++) {
                //每行选中的小球
                if (selectBall.get(i) != null)
                    allBall += selectBall.get(i).values().size();
            }
            //true 满足当前玩法手动选择号码规则
            isMatchItemCount = (selectBall.values().size() >= itemCount &&
                    allBall >= currentMenu.getSelectBallCount());
            if (isMatchItemCount) {
                mBetList.add(currentMenu.clone());
                clearAllBallStatue();
                setBottomBarBettingNumber(mBetList.size());
                setBottomBarLeftText("机选");
            }
        }
        return isMatchItemCount;
    }

    @Override
    protected void onBottonCircleRedDragged() {
        mBetList.clear();
        setBottomBarBettingNumber(mBetList.size());
    }

    @Override
    protected void onBottomRightButtonClick() {
        if (currentMenu == null) currentMenu = menuBeans.get(0);
        if (mBetList.size() > 0) {
            jumpToBetConfirmActivity();
        } else {
            if (addBettingArea())
                jumpToBetConfirmActivity();
            else
                setRandomChecked(MakeRandomUtil.getBall(currentMenu.getItemLineCount(), currentMenu.getSelectBallCount()));
        }
    }

    public void jumpToBetConfirmActivity() {
        //接下来来我们要做的就是将BetList里面的数据进行一个转换；
        if (mBetList.size() <= 0) return;
        ArrayList<String> ballNumber = new ArrayList<>();   //条目上面的title
        ArrayList<String> mode = new ArrayList<>();         //条目下面的title;
        ArrayList<String> numMoney = new ArrayList<>();      //注数和金额；
        int totalMoney = 0;
        int totalBettingNum = 0;
        //将所有的球按照投注界面需要的数据格式组装
        for (LotteryNumberMenuBean bettingBean : mBetList) {
            //模式
            long bettingNumber = bettingBean.getNumber();
            String ballNum = "";
            Map<Integer, Map<Integer, BallItem>> selectBall = bettingBean.getSelectBall();
            for (Map<Integer, BallItem> ballMap : selectBall.values()) {
                int index = 0;
                for (BallItem ball : ballMap.values()) {
                    index++;
                    ballNum += ball.getBallNum();
                    //这个判断是由于有些球需要逗号隔开有的空格隔开
                    if (!TextUtils.isEmpty(ballNum) && index < ballMap.values().size() && bettingBean.isAllowSplit())
                        ballNum += ",";
                    else
                        ballNum += " ";
                }
                if (!ballNum.endsWith(" "))
                    ballNum += " ";
            }
            ballNum = ballNum.substring(0, ballNum.length() - 1);    //去掉最后一个空格
            String oneMode = bettingBean.getMenuName();
            totalMoney += bettingNumber * 2;
            totalBettingNum += bettingNumber;
            mode.add(oneMode);
            ballNumber.add(ballNum);
            numMoney.add(bettingNumber + "注 " + bettingNumber * 2 + "元");
        }



    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
        super.onActivityResult(requestCode, resultCode, intent);
        if (requestCode == 0) {
            mBetList.clear();
            ArrayList<String> selectedNumbers = intent.getStringArrayListExtra("ballNumber"); //球
            ArrayList<String> playModes = intent.getStringArrayListExtra("mode"); //玩法
            ArrayList<String> bettingNums = intent.getStringArrayListExtra("numMoney"); //注数及金额
            Log.e("init-ballNum", FastOk.string(selectedNumbers));
            if (selectedNumbers != null && playModes != null && bettingNums != null) {
                for (int i = 0; i < playModes.size(); i++) {
                    String s = selectedNumbers.get(i);
                    int lineIndex = 0;
                    //这里解析投注界面的投注 解析jumpToBetConfirmActivity()方法里面的组装逻辑
                    for (String bal : s.split(" ")) {
                        for (String b : bal.split(",")) {
                            BallItem item = new BallItem();
                            item.setSelected(true);
                            item.setBallNum(b);
                            //因爲position是从0开始的所以需要data-1
                            int position = Integer.valueOf(b);
                            item.setPosition(position == 0 ? position : position - 1);
                            item.setLineIndex(lineIndex);
                            for (LotteryNumberMenuBean bean : menuBeans) {
                                if (bean.getMenuName().equals(playModes.get(i))) {
                                    onBallCheck(item, bean);
                                    break;
                                }
                            }
                            item.setDefCheckMenu(currentMenu.getMenuId());
                            Log.e("ball->", FastOk.string(item));
                        }
                        //如果itemCount>1 则表明有多行号码选择 每一个data等同于每行选择的号码
                        if (currentMenu.getItemCount() > 1)
                            lineIndex++;
                    }
                    addBettingArea();
                }
            }
            Log.e("format-ballNum", FastOk.string(mBetList));
            setBottomBarBettingNumber(mBetList.size());
        }
    }

    @Override
    protected void sendRandom(Intent intent) {
        super.sendRandom(intent);
        mBetList.clear();
        int num = intent.getIntExtra("num", 0);
        if (num > 0) {
            clearAllBallStatue();
            //开始机选
            for (int i = 0; i < num; i++) {
                setRandomChecked(MakeRandomUtil.getBall(currentMenu.getItemLineCount(), currentMenu.getSelectBallCount()), false);
                addBettingArea();
            }
            //接下来来我们要做的就是将BetList里面的数据进行一个转换；
            ArrayList<String> ballNumber = new ArrayList<>();   //条目上面的title
            ArrayList<String> mode = new ArrayList<>();         //条目下面的title;
            ArrayList<String> numMoney = new ArrayList<>();      //注数和金额；
            int totalMoney = 0;
            int totalBettingNum = 0;

            for (LotteryNumberMenuBean bettingBean : mBetList) {
                //模式
                long bettingNumber = bettingBean.getNumber();
                String ballNum = "";
                Map<Integer, Map<Integer, BallItem>> selectBall = bettingBean.getSelectBall();
                for (Map<Integer, BallItem> ballMap : selectBall.values()) {
                    int index = 0;
                    for (BallItem ball : ballMap.values()) {
                        index++;
                        ballNum += ball.getBallNum();
                        //这个判断是由于有些球需要逗号隔开有的空格隔开
                        if (!TextUtils.isEmpty(ballNum) && index < ballMap.values().size() && bettingBean.isAllowSplit())
                            ballNum += ",";
                        else
                            ballNum += " ";
                    }
                    if (!ballNum.endsWith(" "))
                        ballNum += " ";
                }
                ballNum = ballNum.substring(0, ballNum.length() - 1);    //去掉最后一个空格
                String oneMode = bettingBean.getMenuName();
                totalMoney += bettingNumber * 2;
                totalBettingNum += bettingNumber;
                mode.add(oneMode);
                ballNumber.add(ballNum);
                numMoney.add(bettingNumber + "注 " + bettingNumber * 2 + "元");
            }
            intent.setAction(Constant_Result.EXECRANDOMLOTTERYNUM);
            intent.putExtra("type", mType); //彩种
            intent.putExtra("totalMoney", totalMoney); //总金额
            intent.putExtra("totalNum", totalBettingNum);//总注数f
            intent.putStringArrayListExtra("ballNumber", ballNumber); //球
            intent.putStringArrayListExtra("mode", mode); //玩法及模式
            intent.putStringArrayListExtra("numMoney", numMoney); //注数及金额
            sendBroadcast(intent);
        }
    }

    @Override
    protected void onBottonLeftButtonClick() {
        random();
    }

    private void random() {
        //设置默认菜单玩法
        if (currentMenu == null) currentMenu = menuBeans.get(0);
        String text = getBottomBarleftText();
        if ("机选".equals(text)) {
            //随机选中一个
            setRandomChecked(MakeRandomUtil.getBall(currentMenu.getItemLineCount(), currentMenu.getSelectBallCount()));
            setBottomBarLeftText("清空");
        } else {
            //清空逻辑；
            clearAllBallStatue();
            setBottomBarLeftText("机选");
        }
    }

    //清空数据
    public void clearAllBallStatue() {
        if (currentMenu != null) currentMenu.setSelectBall(null);
        if (adapter != null) adapter.notifyDataSetChanged();
        if (mTvNumberMoney != null) mTvNumberMoney.setVisibility(View.INVISIBLE);
    }

    public void setRandomChecked(List<String> datas) {
        setRandomChecked(datas, true);
    }

    //随机投注
    public void setRandomChecked(List<String> datas, boolean updateUi) {
        int lineIndex = 0;
        for (String data : datas) {
            BallItem item = new BallItem();
            item.setSelected(updateUi);
            item.setBallNum(data);
            //因爲position是从0开始的所以需要data-1
            int position = Integer.valueOf(data);
            item.setPosition(position == 0 ? position : position - 1);
            item.setLineIndex(lineIndex);
            item.setDefCheckMenu(currentMenu.getMenuId());
            //如果itemCount>1 则表明有多行号码选择 每一个data等同于每行选择的号码
            if (currentMenu.getItemCount() > 1)
                lineIndex++;
            onBallCheck(item);
        }
        if (updateUi)
            if (adapter != null) adapter.notifyDataSetChanged();
    }

    @OnClick({R.id.tv_mid_title,R.id.tv_right_option})
    void click(View v) {
        switch (v.getId()) {
            case R.id.tv_mid_title:
                //titlle的点击事件；
                startAnimation(ivTitleIcon, R.anim.rotate_0_180);
                mCenterPopWindow.showAsDropDown(rlBar);
                break;
            case R.id.tv_right_option:
                //这里我们是需要要显示
                mRightMenuPopupWindow.showAsDropDown(tvRightOption);
                break;
        }
    }

    //初始化弹出菜单
    private void initCenterPopupWindow() {
        mCenterPopWindow = new LotteryNumberPopWindow(this);
        mCenterPopWindow.setItemData(menuBeans);
        mCenterPopWindow.setOnItemClickListener(new LotteryNumberPopWindow.OnItemClickListener() {
            @Override
            public void onItemClick(View view, int position) {
                //这里我们执行的逻辑就是根据相应的position显示具体的界面；
                adapter.setDefCheckMenu(position);
                //切换窗口清空数据
                if (currentMenu != null && currentMenu.getMenuId() != menuBeans.get(position).getMenuId()) {
                    clearAllBallStatue();
                }
                currentMenu = menuBeans.get(position);
                setBottomBarLeftText("机选");
            }
        });
        mCenterPopWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                startAnimation(ivTitleIcon, R.anim.rotate_180_360);
            }
        });
    }

    private void initRightPopupWindow() {
        mRightMenuPopupWindow = new GuideMenuPopupWindow(this);

        String title;
        if (PreferenceUtil.isShowMissing(this)) {
            title = "隐藏遗漏";
            if (adapter != null) adapter.setShowMissData(true);
        } else {
            title = "显示遗漏";
            if (adapter != null) adapter.setShowMissData(false);
        }

        mRightMenuPopupWindow.addItem(title, new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                boolean showMissing = PreferenceUtil.isShowMissing(BaseNumberLotteryActivity.this);
                boolean isShowMiss = !showMissing;

                if (isShowMiss) {
                    mRightMenuPopupWindow.setTitle(0, "隐藏遗漏");
                    if (adapter != null) adapter.setShowMissData(true);
                } else {
                    mRightMenuPopupWindow.setTitle(0, "显示遗漏");
                    if (adapter != null) adapter.setShowMissData(false);
                }
                PreferenceUtil.setIsShowMissing(BaseNumberLotteryActivity.this, isShowMiss);

                mRightMenuPopupWindow.dismiss();
            }
        });
        mRightMenuPopupWindow.addItem("历史开奖", new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //跳转到开奖
                Intent intent = new Intent(BaseNumberLotteryActivity.this, LotteryHistoryActivity.class);
                intent.putExtra("type", mType);
                startActivity(intent);
            }
        });
        mRightMenuPopupWindow.addItem("玩法介绍", new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Intent helpIntent = new Intent(BaseNumberLotteryActivity.this, WebHelperActivity.class);
                helpIntent.putExtra("title", "玩法介绍");
                helpIntent.putExtra("code", mType);
                helpIntent.putExtra("isLocal", true);
                startActivity(helpIntent);
            }
        });
    }

    @Override
    protected void onResume() {
        super.onResume();
        mShakeUtils.register();
    }

    @Override
    protected void onPause() {
        super.onPause();
        mShakeUtils.unRegister();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mShakeUtils.unRegister();
    }
}
